package demo.javassist.ibmdemo;

import java.io.IOException;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

/**
 * https://www.ibm.com/developerworks/cn/java/j-dyn0916/
 * 1) 执行这个例子程序是在cmd下测试的，将java代码和package目录一起复制到G:\test目录下
 * 2) javac 编译两个文件
 * 3) java  运行
 * 4) 费了一番周折,最终是测试成功,过程记录在印象笔记"2017年12月20日： javassist | 学习笔记"
 * 
 * @author Wxg
 *
 */
public class JassistTiming {
	public static void main(String[] args) {
//		String strClas = "demo.javassist.ibmdemo.StringBuilder";
//		String strMethod = "buildString";
		JassistTiming jt = new JassistTiming();
//		jt.invoke(strClas, strMethod);
		jt.invoke(args[0], args[1]);
	}
	
	
	public void invoke(String strClas, String strMethod){
		try {
			CtClass clas = ClassPool.getDefault().get(strClas);
			if(clas == null){
				System.err.println("Class " + strClas + " not found");
			}else{
				addTiming(clas, strMethod);
				clas.writeFile();
				System.out.println("Added timing to method " + strClas + "." + strMethod);
			}
		} catch (NotFoundException e) {
			e.printStackTrace();
		} catch (CannotCompileException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void addTiming(CtClass clas, String mname) throws NotFoundException, CannotCompileException{
		CtMethod mold = clas.getDeclaredMethod(mname);
		
		String nname = mname + "$impl";
		mold.setName(nname);
		CtMethod mnew = CtNewMethod.copy(mold, mname, clas, null);
		
		String type = mold.getReturnType().getName();
		StringBuffer body = new StringBuffer();
		body.append("{\nlong start = System.currentTimeMillis();\n");
		if(!"void".equals(type)){
			body.append(type + " result = ");
		}
		body.append(nname + "($$);\n");
		
		body.append("System.out.println(\"Call to method " + mname 
				+ " took \" +\n (System.currentTimeMillis()-start) + "
				+ "\" ms.\");\n");
		if(!"void".equals(type)){
			body.append("return result;\n");
		}
		body.append("}");
		
		mnew.setBody(body.toString());
		clas.addMethod(mnew);
		
		System.out.println("Interceptor method body:");
		System.out.println(body.toString());
	}
	
	
	
	
	
	
	
	
	
	
}
